﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Collections;
using BLToolkit.ComponentModel;
using LED_Utils.MultitrackControl;


namespace Maxel.MultitrackControl
{
    public partial class TracksControl : UserControl,ICustomScale
    {
        public TracksControl()
        {
            InitializeComponent();

            _trackHeight = 75;
        }

        private object _datasource;

        [AttributeProvider(typeof(IListSource))]
        [RefreshProperties(RefreshProperties.Repaint)]
        [DefaultValue(null)]
        [Category("Data")]
        public object DataSource
        {
            get { return _datasource; }
            set
            {
                _datasource = value;
               InitInternal();
            }
        }

        private object _frameSource;

        [AttributeProvider(typeof(IListSource))]
        [RefreshProperties(RefreshProperties.Repaint)]
        [DefaultValue(null)]
        [Category("Data")]
        public object DataSourceFrames
        {
            get { return _frameSource; }
            set
            {
                _frameSource = value;
                //InitFramesInternal();
            }
        }

        private void InitFramesInternal()
        {
           // throw new NotImplementedException();
        }

        public string FramesName { get; set; }

        private void InitInternal()
        {
            if (_datasource == null || !(_datasource is IList))
                return;


            IList listSource = (IList)_datasource;
            foreach (var item in listSource)
            {
                AddTrackInternal(item);
            }
            this.bindingSource1.DataSource = _datasource;
            //this.BindingContext[_datasource].PositionChanged += bindingSource_PositionChanged;
            this.bindingSource1.PositionChanged += bindingSource_PositionChanged;

            if (_datasource is IBindingList)
            {
                IBindingList bindingListSource = (IBindingList)_datasource;
                bindingListSource.ListChanged += new ListChangedEventHandler(bindingListSource_ListChanged);

            }
            //if (_datasource is BindingSource)
            //{
            //    BindingSource bindingSource = (BindingSource)_datasource;
            //    bindingSource.PositionChanged += new EventHandler(bindingSource_PositionChanged);

            //}
            this.timeLinePanel1.Width = 10000;
            PerformScale(100);
        }
        private int _position;
        public int Position
        {
            get {
                return _position; }
            set {
                _position = value;
                EditableTrack track = Tracks.ElementAtOrDefault(_position);
                if (track != null)
                {
                    SelectTrack((EditableTrack)track);
                    track.Select();
                }
            }
        }

        void bindingSource_PositionChanged(object sender, EventArgs e)
        {
            int position = this.BindingContext[_datasource].Position;
            EditableTrack track = Tracks.ElementAtOrDefault(position);
            if (track != null)
            {
                track.Select();
            }
            //Tracks.ElementAt(position).Select();
        }

        void bindingListSource_ListChanged(object sender, ListChangedEventArgs e)
        {
            //throw new NotImplementedException();
            switch (e.ListChangedType )
            {
                case ListChangedType.ItemAdded:
                    AddTrackInternal(((IBindingList)sender)[e.NewIndex]);
                    break;
                case ListChangedType.ItemChanged:
                    break;
                case ListChangedType.ItemDeleted:
                    break;
                case ListChangedType.ItemMoved:
                    break;
              default:
                    break;
            }
        }

        public event EventHandler CurrentChanged;
        private void OnCurrentChanged()
        {
            if (CurrentChanged != null)
            {
                CurrentChanged(this, EventArgs.Empty);
            }
        }

        private object _current;
        public object Current
        {
            get
            {
                return _current;
            }
        }

        private int _trackHeight;
        public int TrackHeight {
            get { return _trackHeight; } 
            set {
                _trackHeight = value;
                foreach (var item in Tracks)
                {
                    item.Height = _trackHeight;
                }
            } 
        }

        private int _timeScaleHeight;
        public int TimeScaleHeight
        {
            get { return timeLinePanel1.Height; }
            set {
                _timeScaleHeight = value;
                timeLinePanel1.Height = value; 
            }
        }

        private IEnumerable<EditableTrack> Tracks
        {
           
            get{return flowLayoutPanel1.Controls.OfType<EditableTrack>();}
        }



        
        protected virtual Control GetEditableTrackControl(object data)
        {
            this.Width = 10000;
            EditableTrack track = new EditableTrack();
            track.Width = 10000;
            track.Height = TrackHeight;
            
            track.DataSource = data.GetType().GetProperty("Frames").GetValue(data,null) ;
            track.CurrentChanged += new EventHandler(track_CurrentChanged);
            track.Click += innerFramesPanel_Click;
            track.FrameControlClick += innerFramesPanel_Click;
            track.InitialScale = InitialScale;
            track.ScaleFactor = (int)ScaleFactor;

            //panel.Margin = Padding.Empty;
            //panel.Padding = Padding.Empty;

            return track;
        }

        void track_CurrentChanged(object sender, EventArgs e)
        {
            _current = ((EditableTrack)sender).Current;
            OnCurrentChanged();
        }

        private void AddTrackInternal(object obj)
        {
           // List<int> ints = new List<int>() { 1, 2, 3, 4, 5 };


            Control panel = GetEditableTrackControl(obj);
            //panel.BackColor = Color.LightYellow;

            //if (panel is EditableTrack)
            //{
            //    ((EditableTrack)panel).DataSource = ints;
            //}
            //panel.Click += new EventHandler(panel_Click); 
            //panel.MouseDown += new MouseEventHandler(panel_MouseDown);

            //Splitter splitter = new Splitter();

            //splitter.Margin = Padding.Empty;
            //splitter.Padding = Padding.Empty;
            //splitter.MinSize  = 1;
            //splitter.MinExtra  = 1;


            //splitter.Size = new System.Drawing.Size(5);
            flowLayoutPanel1.SetFlowBreak(panel, false);
            flowLayoutPanel1.Controls.Add(panel);
            //Controls.Add(splitter);
        }

        private void innerFramesPanel_Click(object sender, EventArgs e)
        {
            if (sender is EditableTrack)
            {
                SelectTrack((EditableTrack)sender);
                SetBindingPosition(this.flowLayoutPanel1.Controls.IndexOf((Control)sender)-1);
            }else
            if (sender == flowLayoutPanel1)
            {
                foreach (Control item in flowLayoutPanel1.Controls)
                {
                    if (!(item is EditableTrack))
                        continue;

                    ((EditableTrack)item).BorderStyle = BorderStyle.None;
                }
                SetBindingPosition(-1);

            }
            else
            {
                foreach (Control item in flowLayoutPanel1.Controls)
                {
                    if (!(item is UserControl))
                        continue;

                    ((UserControl)item).BorderStyle = BorderStyle.None;
                }
                if (sender is UserControl)
                {
                    ((UserControl)sender).BorderStyle = BorderStyle.FixedSingle;
                }
            }
            //_selected = sender;
        }

        private void SelectTrack(EditableTrack sender)
        {
            foreach (Control item in flowLayoutPanel1.Controls)
            {
                if (!(item is EditableTrack))
                    continue;

                ((EditableTrack)item).BorderStyle = BorderStyle.None;
                ((EditableTrack)item).BackColor = Color.FromKnownColor(KnownColor.Transparent);

            }
            ((EditableTrack)sender).BorderStyle = BorderStyle.FixedSingle;
            ((EditableTrack)sender).BackColor = Color.FromArgb(255, 100, 100, 100);
            _current = null;
            OnCurrentChanged(); 
            //((BindingSource)_datasource).Position = this.flowLayoutPanel1.Controls.IndexOf((Control)sender);
        }

        private void SetBindingPosition(int position)
        {
            //if (_datasource is BindingSource)
            //{
            //    ((BindingSource)_datasource).Position = -1;
            //}
            //else if (_datasource is ObjectBinder)
            //{
            //    ((ObjectBinder)_datasource).Position = -1;
            //}
            this.BindingContext[_datasource].Position = position; 
        }

       



        #region ICustomScale Members
        public void PerformScale(int percents)
        {
            timeLinePanel1.InitialScale = InitialScale;
            timeLinePanel1.PerformScale(percents); ;


            foreach (EditableTrack item in Tracks)
            {
                item.InitialScale = InitialScale;
                item.PerformScale(percents);
            }
        }

        public int InitialScale
        {
            get
            {
                return 200;
            }
            set
            {
                
            }
        }

        #endregion

        #region ICustomScale Members


        private float _scaleFactor = 1;
        public float ScaleFactor
        {
            get
            {
                return _scaleFactor;
            }
            set
            {
                _scaleFactor = value;
            }

        }

        #endregion
    }
}
